package net.unix8.server;

import java.io.File;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.json.JSONException;
import org.json.JSONObject;

import com.jfinal.kit.PathKit;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import net.unix8.bean.GetDataBean;
import net.unix8.ftp.easyFTP;
import net.unix8.share.NetworkShare;
import net.unix8.thread.TaskThread;
import net.unix8.tool.Tools;
/**
 * Handler implementation for the echo server.
 */
@Sharable
public class ServerHandler extends ChannelInboundHandlerAdapter {
	//hostList为当前正在进行ftp下载的站点
	public static Map<String, Boolean> hostWorkingMap = new ConcurrentHashMap<String, Boolean>(); 
	public  static boolean addWorking(String host, Boolean df){
		if(!isInWorking(host)){
			hostWorkingMap.put(host, df);
			return true;
		}
		return false;
	}
	public static void removeWorking(String host){
			hostWorkingMap.remove(host);
	}
	public static boolean isInWorkingTrue(String host){
		return (hostWorkingMap.containsKey(host) && (hostWorkingMap.get(host) == true));
	}
	public static boolean isInWorkingFalse(String host){
		return (hostWorkingMap.containsKey(host) && (hostWorkingMap.get(host) == false));
	}
	public static int workingHostsNum(){
		return hostWorkingMap.size();
	}
	public static boolean isInWorking(String host){
		return (hostWorkingMap.containsKey(host));
	}

	//所有当前的站
	public static ArrayList<String> hostListALL = new ArrayList<String>();  
	public  static void addToAll(String host){
		if(!isInAll(host))
			hostListALL.add(host);
	}
	public static void removeFromAll(String host){
		hostListALL.remove(host);
	}
	public static boolean isInAll(String host){
		return hostListALL.contains(host);
	}
	//hostList为当前正在进行ftp下载的站点
	public static Map<String, easyFTP> hostFTPMap = Collections.synchronizedMap(new HashMap<String, easyFTP>()); 
	public  static void addFtp(String host, easyFTP df){
		//if(!isInFtp(host))
			hostFTPMap.put(host, df);
	}
	public static void removeFtp(String host){
		if(isInFtp(host)){
		getFtp(host).disconnect();
		hostFTPMap.remove(host);
		}
	}
	public static boolean isInFtp(String host){
		return hostFTPMap.containsKey(host);
	}
	public static easyFTP getFtp(String host){
		return hostFTPMap.get(host);
	}
	public static int getFtpNos(){
		return hostFTPMap.size();
	}
	
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) {
		ByteBuf in = (ByteBuf) msg;
		String cmd = null, host = null, data = null;
		int id = 0;
		int  bad = 0;//0 SUCCESS, 1 CMD ERROE,2 JSON ERROR

		try {
			int len = in.readableBytes();
			cmd = in.readBytes(len).toString(Charset.forName("UTF-8"));
			//System.out.println(cmd+"\n");
			JSONObject json = new JSONObject(cmd);
			host = json.optString("host",null).trim();
			cmd = json.optString("cmd",null).trim();
			id = json.optInt("id",-1);
			data = json.optString("data",null);

/*			System.out.print("ID:"+id+"\n");
			System.out.print("HOST:"+json.opt("host")+"\n");
			System.out.print("CMD:"+json.opt("cmd")+"\n");
			System.out.print("DATA:"+json.opt("data")+"\n");
*/
			
			if(true){	
				if(host != null && cmd != null && id != -1 && Tools.checkIP(host)){				
					ServerHandler.addToAll(host);//增加新的站点
					bad = 0;
					if(cmd.equals("data") && data != null){
						//Thread downThread = new DownloadFile(ctx.channel().id(),id,host,null,null,null,data,null);
						//NetworkShare.taskPool.execute(downThread);
					}else if(cmd.equals("source")){
						if(Tools.checkIP(host)) {
							NetworkShare.paodianHost= host;
						}
						boolean status = false;
						String pathString = PathKit.getWebRootPath() + "/pdata/source_list";
						File file = new File(pathString);       
						if  (file.exists()){status = true;} 
						sendPoint(ctx,host,id,status);
					}else if(cmd.equals("mtime")){
						//System.out.print("MTIME:"+json.optString("time","")+"   " + Tools.dateToStamp(json.optString("time","")));
						String stime = json.optString("time","");
						String sql = json.optString("sql","");
						String[] aa = stime.split("\\.");
						if(aa.length == 2){
							long time1 = Tools.convert2long2(aa[0]) * 1000l;//时间落后
							long time = time1  + 28800000000l; //微秒						
							aa[1] = "0."+aa[1];
							long time2 = (long)(Double.valueOf(aa[1]) * 1000000);//微秒			
							time = time + time2;
							if(time != 0){	
								boolean useSql;
								if(sql.equals("sql"))
									useSql = true;
								else
									useSql = false;
								//Thread getThread = new GetTimeData(ctx.channel().id(),id,host,time,json.optLong("interval",2),useSql);
								//NetworkShare.taskPool.execute(getThread);
								NetworkShare.getDataQueue.offer(new GetDataBean(ctx.channel().id(),id,host,time,json.optLong("interval",2),useSql));
							}else bad = 2;
						}
						else
							bad = 1;
					}else{
						Thread clientConnectThread = new TaskThread(host,cmd,ctx.channel().id(),id);
						NetworkShare.taskPool.execute(clientConnectThread);
					}

				}else{
					bad = 1;
				}
			}
		} catch(Exception e) {
			ReferenceCountUtil.release(msg); // (2)
			bad = 2;
			e.printStackTrace();
		}
		
		if(bad == 0) return;
		JSONObject studentJSONObject = new JSONObject();  
		String errorString = "UNKNOWN ERROR";
		try {  
			studentJSONObject.put("host", host);
			studentJSONObject.put("id", id);  
			studentJSONObject.put("cmd", "data"); 
			studentJSONObject.put("status", false);  
			if(bad == 1){
				errorString = "CMD ERROR";
			}else if(bad == 2){
				errorString = "JSON ERROR";
			}
			studentJSONObject.put("data", errorString);  
		} catch (JSONException e) {  
			e.printStackTrace();  
		}  
		
		final ByteBuf firstMessage;
		firstMessage = Unpooled.buffer(100);
		firstMessage.writeCharSequence(studentJSONObject.toString(), Charset.forName("UTF-8"));
		ctx.writeAndFlush(firstMessage);
		//firstMessage.release();

		/*
		String txt = "Hello,I'm client.";
		final ByteBuf firstMessage;
		firstMessage = Unpooled.buffer(100);
        firstMessage.writeCharSequence(txt, Charset.forName("UTF-8"));
		Channel remoteChannel = NetworkShare.clientGroup.find(ctx.channel().id());
		if(remoteChannel != null){
			System.out.println("SEND JSON SUCCESS:");
			remoteChannel.writeAndFlush(firstMessage);
		}*/
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) {
		ctx.flush();
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		InetSocketAddress insocket = (InetSocketAddress) ctx.channel()
				.remoteAddress();
		String clientIP = insocket.getAddress().getHostAddress();
		System.out.println("3333 端口主机断开连接， ip:"+clientIP);
		NetworkShare.clientGroup.remove(ctx.channel());
		super.channelInactive(ctx);
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		InetSocketAddress insocket = (InetSocketAddress) ctx.channel()
				.remoteAddress();
		String clientIP = insocket.getAddress().getHostAddress();
		System.out.println("3333 端口主机异常 ip:"+clientIP);
		NetworkShare.clientGroup.remove(ctx.channel());
		// Close the connection when an exception is raised.
		cause.printStackTrace();
		ctx.close();
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception{
		InetSocketAddress insocket = (InetSocketAddress) ctx.channel()
				.remoteAddress();
		String clientIP = insocket.getAddress().getHostAddress();
		System.out.println("3333 端口主机建立到服务器的连接 :"+clientIP);
		NetworkShare.clientGroup.add(ctx.channel());
		super.channelActive(ctx);

	}
	private void sendPoint(ChannelHandlerContext ctx,String host, int id, boolean status) {
		String fileName = "source_list";
		JSONObject studentJSONObject = new JSONObject();  
		try {  
			studentJSONObject.put("host", host);
			studentJSONObject.put("id", id);  
			studentJSONObject.put("cmd", "source"); 
			studentJSONObject.put("status", status);  
			if(!status){
				fileName = "Can not find the source file";
			}
			studentJSONObject.put("data", fileName);  
		} catch (JSONException e) {  
			e.printStackTrace();  
		}  

		final ByteBuf firstMessage;
		firstMessage = Unpooled.buffer(100);
		firstMessage.writeCharSequence(studentJSONObject.toString(), Charset.forName("UTF-8"));
		ctx.writeAndFlush(firstMessage);
	}
}
